import AnimatedComponent from "./components/common-components/AnimatedComponent";
import GCToast from "./components/common-components/GCToast";
import ClassicComponent from "./components/game/ClassicComponent";
import HeaderComponent from "./components/game/HeaderComponent";
import MenuComponent from "./components/game/MenuComponent";
import TimeLimitedComponent from "./components/game/TimeLimitedComponent";
import DailyRewardWnd from "./components/wnds/DailyRewards";
import LeaderboardComp from "./components/wnds/LeaderboardComp";
import TipComp from "./components/wnds/TipComp";
import GCGlobal from "./GCGlobal";
import StateMachine from "./sm/StateMachine";
import { ClassicState } from "./sm/states/ClassicState";
import { InitState } from "./sm/states/InitState";
import { MenuState } from "./sm/states/MenuState";
import { SurvivalState } from "./sm/states/SurvivalState";
import { TimeLimitedState } from "./sm/states/TimeLimitedState";


export interface ISMEventData {
    type: string;
    res?: any;
}

const { ccclass, property } = cc._decorator;

@ccclass
export default class GameLogic extends cc.Component {
    sm: StateMachine<GameLogic> = null;

    @property(AnimatedComponent)
    content: AnimatedComponent = null;

    @property(HeaderComponent)
    header: HeaderComponent = null;

    @property(MenuComponent)
    menu: MenuComponent = null;

    @property(ClassicComponent)
    classicComp: ClassicComponent = null;

    @property(DailyRewardWnd)
    dailyRewardWnd: DailyRewardWnd = null;

    @property(LeaderboardComp)
    leaderboard: LeaderboardComp = null;

    @property(TimeLimitedComponent)
    timeLimited: TimeLimitedComponent = null;

    @property(TipComp)
    tip: TipComp = null;

    protected async onLoad() {
        this.sm = new StateMachine();
        this.sm.logic = this;

        this.sm.register(new InitState('init'));
        this.sm.register(new MenuState('menu'));
        this.sm.register(new ClassicState('classic'));
        this.sm.register(new TimeLimitedState('timelimited'));
        this.sm.register(new SurvivalState('survival'));

        await this.sm.setup('init');

        this.sm.to('menu');
    }

    protected onEnable(): void {
        this.node.on('sm-event', this.onSMEvent, this);
    }

    protected onDisable(): void {
        this.node.off('sm-event', this.onSMEvent, this);
    }

    /**
     * 这里的转换只包括UI上的转换。
     * 在转换过程中。整个UI会被锁定，即不接受用户任何输入
     */
    async doTransform(from: string, to: string) {
        if (from == '' && to == 'init') {
            return this.fromNothingToInit();
        }
        if (from == 'init' && to == 'menu') {
            return this.fromInitToMenu();
        }

        if (from == 'menu' && to == 'classic') {
            return this.fromMenuToClassic();
        }

        if (from == 'classic' && to == 'menu') {
            return this.fromClassicToMenu();
        }

        if (from == 'menu' && to == 'timelimited') {
            return this.fromMenuToClassic();
        }
        if (from == 'timelimited' && to == 'menu') {
            return this.fromClassicToMenu();
        }

        if (from == 'menu' && to == 'survival') {
            return this.fromMenuToClassic();
        }
        if (from == 'survival' && to == 'menu') {
            return this.fromClassicToMenu();
        }
    }

    async fromNothingToInit() {
    }

    async fromInitToMenu() {
        await this.content.playAnimation('init-2-menu');
    }

    async fromMenuToClassic() {
        await this.content.playAnimation('menu-2-classic');
    }

    async fromClassicToMenu() {
        await this.content.playAnimation('classic-2-menu');
    }

    // -------------- 其他组件传递的消息 -------------- //

    onSMEvent(evt: cc.Event.EventCustom) {
        const data = evt.getUserData() as ISMEventData;

        if (!data) {
            cc.error(`[onSMEvent] evt.getUserData() is null`);
            return;
        }

        const state = this.sm.state;

        if (!['classic', 'timelimited', 'survival'].includes(state)) {
            cc.error(`[onSMEvent] wrong state, currState: ${this.sm.state}`);
            return;
        }

        const stateSM = this.sm.getState();
        stateSM.process(this, data.type, data.res);
    }


    // -------------- 工具方法 -------------- //

    sleep(ms: number) {
        return new Promise((resolve) => {
            this.scheduleOnce(resolve, ms / 1000);
        });
    }


    // -------------- 主页按钮点击事件 -------------- //

    protected async onClassicEntryClicked() {
        if (this.sm.state != 'menu') {
            cc.error('[onClassicEntryClicked] this.sm.state !== "menu"');
            return;
        }
        this.sm.to('classic');
    }

    protected async onTimeLimitedEntryClicked() {
        if (this.sm.state != 'menu') {
            cc.error('[onClassicEntryClicked] this.sm.state !== "menu"');
            return;
        }
        this.sm.to('timelimited');
    }

    protected onClaimDailyRewardBtnClicked() {
        if (this.sm.state !== 'menu') {
            cc.log(`[onClaimDailyRewardBtnClicked] wrong state: ${this.sm.state}`);
            return
        }

        this.sm.getState().process(this, 'claim-daily-reward');
    }

    protected onSurvivalEntryClicked() {
        if (this.sm.state != 'menu') {
            cc.error('[onClassicEntryClicked] this.sm.state !== "menu"');
            return;
        }

        if (GCGlobal.Account.survivalCount <= 0) {
            GCToast.toast('无尽模式次数消耗完毕');
            return;
        }

        this.sm.to('survival');
    }

    protected onLeaderboardBtnClicked() {
        if (this.sm.state !== 'menu') return;
        if (this.leaderboard.node.active) return;

        this.leaderboard.showWnd();
    }

    protected onTipBtnClicked() {
        if (this.sm.state !== 'menu') return;
        if (this.tip.node.active) return;

        this.tip.showWnd();
    }
}
